package nl.hanze.monoalphabetic.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import nl.hanze.monoalphabetic.domain.CharacterFrequency;
import nl.hanze.monoalphabetic.domain.StringCount;
import org.apache.commons.math3.stat.Frequency;

/**
 *
 * @author alex
 */
public class TextStatistics {

    private ArrayList<CharacterFrequency> singleCharacter;
    private ArrayList<String> topTwoLetterWords, topThreeLetterWords;
    private ArrayList<String> topTwoLetterCombinations, topThreeLetterCombinations;
    private int topListLength;

    public TextStatistics() {
        topListLength = 26;
        //Maak datastructuren aan
        singleCharacter = new ArrayList<>(26);

        topTwoLetterWords = new ArrayList<>();
        topThreeLetterWords = new ArrayList<>();

        topTwoLetterCombinations = new ArrayList<>();
        topThreeLetterCombinations = new ArrayList<>();
    }

    public void generateStatistics(String text) {
        //Wis oude statistieken
        clearLists();
        //Datastructuren
        HashMap<String, Integer> twoLetterWords = new HashMap<>();
        HashMap<String, Integer> threeLetterWords = new HashMap<>();

        HashMap<String, Integer> twoLetterCombination = new HashMap<>();
        HashMap<String, Integer> threeLetterCombination = new HashMap<>();

        Frequency frequency = new Frequency();

        //Loop door text split op spaties.
        for (String t : text.split(" ")) {
            StringBuilder s = new StringBuilder();
            //Nieuw woord
            Character onePrevious = null;
            Character twoPrevious = null;
            //Loop door characters
            for (Character c : t.toCharArray()) {
                //Zet om naar lowercase           
                c = Character.toLowerCase(c);
                //Check of het binnen het bereik valt
                if (c >= 'a' && c <= 'z') {
                    //Voeg toe aan stringbuilder 
                    s.append(c);
                    //Voeg toe aan frequency
                    frequency.addValue(c);

                    //Voeg combinatie van 3 letters toe
                    if (twoPrevious != null) {
                        String temp = "" + twoPrevious + onePrevious + c;

                        if (threeLetterCombination.get(temp) == null) {
                            threeLetterCombination.put(temp, 1);
                        } else {
                            int count = threeLetterCombination.get(temp);
                            threeLetterCombination.put(temp, ++count);
                        }

                        //Letters opnieuw toewijzen
                        twoPrevious = onePrevious;
                        //onePrevious = c;

                    } //Voeg combinatie van 2 letters toe
                    if (onePrevious != null) {
                        String temp = "" + onePrevious + c;

                        if (twoLetterCombination.get(temp) == null) {
                            twoLetterCombination.put(temp, 1);
                        } else {
                            int count = twoLetterCombination.get(temp);
                            twoLetterCombination.put(temp, ++count);
                        }
                        //Letters opnieuw toewijzen
                        twoPrevious = onePrevious;
                        //onePrevious = c;
                    }

                    onePrevious = c;
                }
            }

            //Zet stringbuilder om naar string                
            String tempString = s.toString();
            //Twee letter woorden
            if (tempString.length() == 2) {
                if (twoLetterWords.get(tempString) == null) {
                    twoLetterWords.put(tempString, 1);
                } else {
                    int count = twoLetterWords.get(tempString);
                    twoLetterWords.put(tempString, ++count);
                }

            } //Drie letter woorden
            else if (tempString.length() == 3) {
                if (threeLetterWords.get(tempString) == null) {
                    threeLetterWords.put(tempString, 1);
                } else {
                    int count = threeLetterWords.get(tempString);
                    threeLetterWords.put(tempString, ++count);
                }
            }
        }
        //Zet datastructuren om
        //Set frequencies in lijst
        for (int i = 0; i < 26; i++) {
            singleCharacter.add(new CharacterFrequency((char) (i + 'a'), frequency.getPct((char) (i + 'a'))));
        }
        //
        topTwoLetterWords = convertHashMap(twoLetterWords);
        topThreeLetterWords = convertHashMap(threeLetterWords);
        topTwoLetterCombinations = convertHashMap(twoLetterCombination);
        topThreeLetterCombinations = convertHashMap(threeLetterCombination);


    }

    private ArrayList<String> convertHashMap(HashMap<String, Integer> hashmap) {
        ArrayList<StringCount> list = new ArrayList<>();
        ArrayList<String> returnList = new ArrayList<>();

        for (Map.Entry entry : hashmap.entrySet()) {
            list.add(new StringCount((String) entry.getKey(), (Integer) entry.getValue()));
        }
        //Sorteer lijst
        Collections.sort(list);
        //Vul lijst met top 26 combinaties
        int max = list.size() > topListLength ? topListLength : list.size();
        for (int i = 0; i < max; i++) {
            returnList.add(list.get(i).getString());
        }

        return returnList;
    }

    private void clearLists(){
        singleCharacter.clear();
        
        topTwoLetterWords.clear();
        topThreeLetterWords.clear();
        
        topTwoLetterCombinations.clear();
        topThreeLetterCombinations.clear();
    }
        

    public ArrayList<CharacterFrequency> getSingleCharacter() {
        return singleCharacter;
    }

    public ArrayList<String> getTopThreeLetterCombinations() {
        return topThreeLetterCombinations;
    }

    public ArrayList<String> getTopThreeLetterWords() {
        return topThreeLetterWords;
    }

    public ArrayList<String> getTopTwoLetterCombinations() {
        return topTwoLetterCombinations;
    }

    public ArrayList<String> getTopTwoLetterWords() {
        return topTwoLetterWords;
    }
}
